home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Best of MacTutor - S…e Code for Volumes 1 to 5
/
The Best of MacTutor - Source Code for Volume 1-5 (Wayzata Technology)(6031)(1990).bin
/
Source Code
/
#14 (Nov 86)
/
Munkki's Forth ok
/
Sources
/
Commented Teddy Source
next >
Wrap
Text File
|
1986-09-06
|
25KB
|
809 lines
( Teddy -- Text Editor )
( Contains MacForth-like extensions to Mach I in addition to the editor.
Type TED to call the editor at any time. The MacForth-style extensions
are mostly undocumented here. Look for examples in this source. )
( Anew:
Used in the form: ANEW PROGRAM_NAME. It tries to find the PROGRAM_NAME
and forget it if it is found. It then creates PROGRAM_NAME and continues.
It should be used in the beginning of the program. Old versions are then
automatically forgotten, if they exist. )
ONLY FORTH DEFINITIONS
ALSO MAC ALSO ASSEMBLER
: ANEW { | LEN }
32 WORD DUP C@ 1+ NEGATE -> LEN
FIND SWAP DROP
IF LEN >IN +! FORGET CALL DRAWMENUBAR THEN
LEN >IN +!
CREATE DOES> DROP
;
( Heapvar:
Used in the form: HEAPVAR VARIABLE_NAME. If VARIABLE_NAME exists, it
returns the handle from VARIABLE_NAME to the heap. It should be used
before ANEW to free space from the heap. )
: HEAPVAR
32 WORD
FIND IF LINK>BODY EXECUTE
@ DUP
IF DUP CALL HUNLOCK DROP
CALL DISPOSHANDLE DROP ELSE DROP THEN
ELSE DROP
THEN
;
: RECT
CREATE
SWAP 2SWAP SWAP
W, W, W, W,
;
GLOBAL
CODE !RECT
MOVE.L (A6)+,A0
MOVE.W 14(A6),(A0)+
MOVE.W 10(A6),(A0)+
MOVE.W 6(A6),(A0)+
MOVE.W 2(A6),(A0)+
ADDA.L #16,A6
RTS
END-CODE
GLOBAL
CODE OFF
MOVEA.L (A6)+,A0
CLR.L (A0)
RTS
END-CODE
MACH
GLOBAL
CODE ON
MOVEA.L (A6)+,A0
MOVE.L #-1,(A0)
RTS
END-CODE
GLOBAL
CODE SCALE
MOVE.L (A6)+,D0
BMI.S @1
MOVE.L (A6),D1
ASL.L D0,D1
MOVE.L D1,(A6)
RTS
@1 MOVE.L (A6),D1
NEG.L D0
ASR.L D0,D1
MOVE.L D1,(A6)
RTS
END-CODE
GLOBAL
CODE @MOUSE
SUBQ.L #4,A6
MOVE.L A6,-(A7)
_GETMOUSE
RTS
END-CODE
HEADER TEDDY.W2 DC.L 0
HEADER TEDDY.T2 DC.L 0
HEADER TEDDY.S2 DC.L 0
CODE CLICKPROC
MOVEM.L D1-D3/A0-A4,-(A7)
CLR.L -(A7)
MOVE.L A7,-(A7)
_GETMOUSE ( Where is the mouse cursor? )
MOVE.L (A7)+,D0
SWAP.W D0 ( Get the Y-location to D0.W )
CMP.W #18,D0 ( Is Mouse.Y smaller than 18? )
BLT.S @1
MOVE.L TEDDY.W2,A0
MOVE.W 20(A0),D1
SUB.W #16,D1
CMP.W D1,D0 ( Is Mouse.Y below the text? )
BGE.S @2
@4 MOVEM.L (A7)+,D1-D3/A0-A4
MOVEQ.L #1,D0
@3 RTS
@1 CLR.W -(A7) ( Are we allowed to scroll down? )
MOVE.L TEDDY.S2,-(A7)
_GETCTLVALUE
MOVE.W (A7)+,D0
BEQ.S @4 ( If we are on top, do nothing )
SUBQ.W #1,D0 ( Scroll one line up )
MOVE.L TEDDY.S2,-(A7)
MOVE.W D0,-(A7)
_SETCTLVALUE
CLR.W -(A7)
MOVE.W #11,-(A7) ( One line = 11 pixels )
MOVE.L TEDDY.T2,-(A7)
_TESCROLL ( Scroll the text )
MOVEM.L (A7)+,D1-D3/A0-A4
MOVEQ.L #1,D0
RTS
@2 CLR.W -(A7)
MOVE.L TEDDY.S2,-(A7)
_GETCTLVALUE ( Where are we? )
MOVE.W (A7)+,D3
CLR.W -(A7)
MOVE.L TEDDY.S2,-(A7)
_GETMAXCTL ( How high can we go? )
MOVE.W (A7)+,D0
CMP.W D0,D3
BGE.S @4
ADDQ.W #1,D3 ( Scroll one line... )
MOVE.L TEDDY.S2,-(A7)
MOVE.W D3,-(A7)
_SETCTLVALUE
CLR.W -(A7)
MOVE.W #-11,-(A7)
MOVE.L TEDDY.T2,-(A7)
_TESCROLL
MOVEM.L (A7)+,D1-D3/A0-A4
MOVEQ.L #1,D0
RTS
END-CODE
( The following routine is quite simple. All it does is search a string
for another one ignoring case and it returns the offset or a flag. )
CODE FINDER ( ?STR ?LEN SEARCHSTR SEARCHLEN -- OFFSET )
MOVEM.L D0-D7/A0-A4,-(A7)
MOVE.L (A6)+,D0
MOVE.L (A6)+,A0
MOVE.L (A6)+,D1
MOVE.L (A6)+,A1
MOVE.W D0,D2
SUB.W D1,D2
CLR.L D7
@1 CLR.W D3
@2 MOVE.B 0(A0,D3.W),D4
BMI.S @3
CMP.B #96,D4
BLT.S @3
SUB.B #32,D4 ( Remove case )
@3 MOVE.B 0(A1,D3.W),D5
BMI.S @4
CMP.B #96,D5
BLT.S @4
SUB.B #32,D5 ( Remove case )
@4 CMP.B D4,D5 ( Is a char equal to another? )
BNE.S @5
ADDQ.W #1,D3 ( It was, one match )
CMP.W D1,D3 ( Have we found the string? )
BLT.S @2
MOVE.L D7,-(A6)
MOVEM.L (A7)+,D0-D7/A0-A4
RTS
@5 ADDQ.L #1,A0 ( No match...yet )
ADDQ.L #1,D7
DBRA D2,@1 ( Look again? )
MOVE.L #-1,-(A6) ( No match...return -1 )
MOVEM.L (A7)+,D0-D7/A0-A4
RTS
END-CODE
( 4ASCII nnnn converts the 4 character string into its numeric value it
can only be used in the immediate mode. Examples below )
: 4ASCII
0
4 0 DO
8 SCALE 0 WORD 1+ C@ +
LOOP
;
ONLY FORTH ALSO MAC
4ASCII TEXT CONSTANT "TEXT
4ASCII DRVR CONSTANT DRIVER
4ASCII MACA CONSTANT "MACA
HEX AB0 CONSTANT TESCRAP.LEN ( Global TeEdit private scrap variables )
AB4 CONSTANT TESCRAP.HANDLE DECIMAL
NEW.WINDOW TEDDY.W
" Text Editor" TEDDY.W TITLE
50 0 304 480 TEDDY.W BOUNDS
ZOOM VISIBLE CLOSEBOX GROWBOX TEDDY.W ITEMS
400 4000 TERMINAL TEDDY.TASK
NEW.MBAR TEDDY.BAR
900 CONSTANT APPLEID
NEW.MENU APPLEMENU
HERE 1 C, 20 C, APPLEMENU TITLE
" About Edit...;(-" APPLEMENU ITEMS ( Add DAs later )
0 APPLEID APPLEMENU BOUNDS
901 CONSTANT TFILEID
NEW.MENU TFILE
" File" TFILE TITLE
" Open/O;Save/S;Save as..." TFILE ITEMS
0 TFILEID TFILE BOUNDS
902 CONSTANT TEDITID
NEW.MENU TEDITMENU
" Edit" TEDITMENU TITLE
" Cut/X;Copy/C;Paste/V;Select All & Copy;-(;Find/F;Again/G("
TEDITMENU ITEMS
0 TEDITID TEDITMENU BOUNDS
: ADD.DRVRS ( Add desk accessories )
APPLEMENU @ DRIVER CALL ADDRESMENU
;
NEW.CONTROL TEDDY.SB
VSCROLLBAR VISIBLE 100 0 TEDDY.SB ITEMS
: DAHANDLER { ITEM | Daname }
ITEM 2 > IF ( We must open a desk accessory )
256 CALL NEWPTR -> DANAME ( Get us a STR255 for the name )
APPLEMENU @ ITEM DANAME CALL GETITEM
DANAME CALL OPENDESKACC DROP ( Open the desk accessory )
DANAME CALL DISPOSPTR ( Give the String back )
ELSE
ITEM 1 = ( The about edit alert should be shown. The resource must
be added separately to Mach I. )
IF 900 0 CALL ALERT DROP THEN THEN
;
HEX 44 CONSTANT txFont ( Offsets in a window record )
46 CONSTANT txFace
48 CONSTANT txMode
4A CONSTANT txSize
6C CONSTANT WindowKind DECIMAL
VARIABLE TEDDY.T ( PLACEHOLDER FOR TEXT HANDLE )
VARIABLE ACTIVE? ( ACTIVE FLAG )
VARIABLE MUSTCONVERT ( SCRAP CONVERSION FLAG )
20 CONSTANT UPARROW ( Part codes )
21 CONSTANT DOWNARROW
22 CONSTANT PAGEUP
23 CONSTANT PAGEDOWN
129 CONSTANT THUMB
VARIABLE CURMAX ( Current scroll bar range )
VARIABLE CURSET ( Current scroll bar setting )
: CORRECT.CONTROL.RANGE
CURMAX @ TEDDY.T @ @ 94 + W@ 1- 0 MAX DUP CURMAX ! = NOT
IF TEDDY.SB @ CURMAX @ CALL SETMAXCTL THEN
;
: CORRECT.CONTROL ( Set scroll bar )
CURSET @ ( Look at the destination RECT for the position )
18 TEDDY.T @ @ W@ L_EXT - 11 / DUP CURSET ! = NOT
IF TEDDY.SB @ CURSET @ CALL SETCTLVALUE THEN
;
: TOO.HIGH.TEDDY ( Autoscroll, when typing )
0 TEDDY.W 20 + W@ 40 - TEDDY.T @ @ 16 + W@ L_EXT - DUP 11 MOD -
?DUP IF ( If tescroll is called with 0 0, the caret disappears! )
TEDDY.T @ CALL TESCROLL
ELSE DROP THEN
CORRECT.CONTROL
;
: TOO.LOW.TEDDY ( Autoscroll, when typing )
0 29 TEDDY.T @ @ 16 + W@ L_EXT - DUP 11 MOD -
TEDDY.T @ CALL TESCROLL
CORRECT.CONTROL
;
: CORRECTSCROLL ( If the user is typing, check if we should scroll. )
TEDDY.T @ @ 32 + DUP W@ SWAP 2+ W@ = ( Do we have a caret? )
IF TEDDY.T @ @ 16 + W@ L_EXT 29 < IF TOO.LOW.TEDDY ELSE
TEDDY.T @ @ 16 + W@ L_EXT
TEDDY.W 20 + W@ 40 - > IF TOO.HIGH.TEDDY THEN
THEN
THEN
;
CREATE TEMR 8 ALLOT ( Temporary storage )
: SCRAP->TE ( Convert global scrap to TeScrap )
0 "TEXT TEMR CALL GETSCRAP 0> ( Is there text? )
IF TESCRAP.HANDLE @ "TEXT TEMR CALL GETSCRAP TESCRAP.LEN W! THEN
MUSTCONVERT OFF ( The scrap does not have to be converted just now )
;
: TE->SCRAP
MUSTCONVERT @ ( Are there any changes after SCRAP->TE? )
IF
CALL ZEROSCRAP DROP ( Zero scrap to clear non-text entries )
TESCRAP.LEN W@ "TEXT TESCRAP.HANDLE @ @ CALL PUTSCRAP DROP
THEN
;
: CLEAR.TESCRAP ( Word used to clear tescrap when it is not needed )
TESCRAP.HANDLE @ 0 CALL SETHANDLESIZE DROP
0 TESCRAP.LEN W!
;
VARIABLE OLDPORT ( Used to save the current window before a dialog )
CREATE DLOG900 0 , ( Handle storage for our "FIND" dialog )
VARIABLE DEVENT ( Dialog "event" )
( You can se the following strings from Forth and then use "aGain" to
replace any untypeable characters. Do a find or replace, then set
teddy.f1 and f2 and choose "aGain". This will do the previous
operation with the new strings! )
CREATE TEDDY.F1 256 ALLOT ( String to find )
CREATE TEDDY.F2 256 ALLOT ( Replace string )
( The following part finds Teddy.F1 from the text )
: TFIND.REALLY { | SELEND STRSTART }
TEDDY.T @ @ 34 + W@ -> SELEND
TEDDY.T @ @ 62 + @ @ -> STRSTART
TEDDY.F1 COUNT ?DUP IF
STRSTART SELEND +
TEDDY.T @ @ 60 + W@ SELEND -
DUP TEDDY.F1 C@ > IF
FINDER DUP
0< IF DROP 10 CALL SYSBEEP 0 0 TEDDY.T @ CALL TESETSELECT
ELSE
SELEND + TEDDY.F1 C@ + DUP TEDDY.T @ CALL TESETSELECT
THEN
ELSE 2DROP 2DROP 10 CALL SYSBEEP 0 0 TEDDY.T @ CALL TESETSELECT THEN
CORRECTSCROLL ELSE DROP THEN
;
( The following finds Teddy.F1 and replaces it with Teddy.F2 )
: TEDDY.REPLACE { | SELEND STRSTART }
TEDDY.T @ @ 34 + W@ -> SELEND
TEDDY.T @ @ 62 + @ @ -> STRSTART
TEDDY.F1 COUNT ?DUP IF
STRSTART SELEND +
TEDDY.T @ @ 60 + W@ SELEND -
DUP TEDDY.F1 C@ > IF
FINDER DUP
0< IF DROP 10 CALL SYSBEEP 0 0 TEDDY.T @ CALL TESETSELECT
ELSE DUP
SELEND + TEDDY.F1 C@ OVER + TEDDY.T @ CALL TESETSELECT
TEDDY.T @ CALL TEDELETE
TEDDY.F2 COUNT TEDDY.T @ CALL TEINSERT
SELEND + TEDDY.F2 C@ + DUP TEDDY.T @ CALL TESETSELECT
THEN
ELSE 2DROP 2DROP 10 CALL SYSBEEP 0 0 TEDDY.T @ CALL TESETSELECT THEN
CORRECTSCROLL ELSE DROP THEN
;
: TEDDYFIND.SUB ( Find or replace according to button )
DEVENT W@ CASE
1 OF TFIND.REALLY ENDOF
2 OF TEDDY.REPLACE ENDOF
ENDCASE
;
: TEDDYFIND
TE->SCRAP ( Forth receives an activate when the dialog is gone. )
( The scrap must be saved to preserve it. )
TEDDY.T @ CALL TEDEACTIVATE
DLOG900 @ 0= IF 900 0 -1 CALL GETNEWDIALOG DLOG900 !
ELSE DLOG900 @ CALL BRINGTOFRONT DLOG900 @ CALL SHOWWINDOW THEN
OLDPORT CALL GETPORT
DLOG900 @ CALL SETPORT ( Set the dialog port )
BEGIN
0 DEVENT CALL MODALDIALOG ( Call this until the user has finished )
DEVENT W@ 4 < UNTIL
OLDPORT @ CALL SETPORT ( Reset "predialog" environment )
DLOG900 @ 5 PAD PAD 4 + PAD 8 + CALL GETDITEM
PAD 4 + @ TEDDY.F1 CALL GETITEXT ( Set Teddy.F1 )
DLOG900 @ 6 PAD PAD 4 + PAD 8 + CALL GETDITEM
PAD 4 + @ TEDDY.F2 CALL GETITEXT ( Set Teddy.F2 )
DLOG900 @ CALL HIDEWINDOW
TEDDY.T @ CALL TEACTIVATE
TEDITMENU @ 7 CALL ENABLEITEM
TEDDYFIND.SUB
;
( Handle Cut/Copy/Paste and others for Teddy and DAs )
: TEDITHANDLER { ITEM }
CALL FRONTWINDOW TEDDY.W = IF ( Editor cut/paste )
ITEM CASE
1 OF TEDDY.T @ CALL TECUT MUSTCONVERT ON ENDOF
2 OF TEDDY.T @ CALL TECOPY MUSTCONVERT ON ENDOF
3 OF TESCRAP.LEN W@
TEDDY.T @ @ 60 + W@
TEDDY.T @ @ 34 + W@ TEDDY.T @ @ 32 + W@ - -
+ 32767 < IF
TEDDY.T @ CALL TEPASTE
ELSE 5 CALL SYSBEEP 5 CALL SYSBEEP THEN ENDOF
4 OF 0 TEDDY.T @ @ 60 + W@ TEDDY.T @ CALL TESETSELECT
TEDDY.T @ CALL TECOPY MUSTCONVERT ON ENDOF
6 OF TEDDYFIND ENDOF
7 OF TEDDYFIND.SUB ENDOF
ENDCASE
CORRECT.CONTROL.RANGE
CORRECTSCROLL
ELSE ( DA cut/copy/paste...Undo is left for you to add... )
CALL FRONTWINDOW
WINDOWKIND + W@ L_EXT 0< IF ITEM 4 < IF ITEM 1+ CALL SYSEDIT DROP THEN
THEN
THEN
;
ALSO ASSEMBLER
( Here we have support for SFGETFILE and SFPUTFILE these routines are
similar to the one in the Mach I manual. )
HEADER TYPES DC.B 'TEXT'
HEADER GPROMPT DC.B 20
DC.B 'Please select a file'
HEADER PPROMPT DC.B 18
DC.B 'Please type a name'
CODE TEDDYGETFILE
MOVE.W #50,-(A7)
MOVE.W #50,-(A7)
PEA GPROMPT
CLR.L -(A7)
MOVE.W #1,-(A7)
PEA TYPES
CLR.L -(A7)
MOVE.L (A6)+,-(A7)
MOVE.W #2,-(A7)
_PACK3
RTS
END-CODE
CODE TEDDYPUTFILE
MOVE.W #50,-(A7)
MOVE.W #50,-(A7)
PEA PPROMPT
MOVE.L (A6)+,-(A7)
CLR.L -(A7)
MOVE.L (A6)+,-(A7)
MOVE.W #1,-(A7)
_PACK3
RTS
END-CODE
ONLY FORTH ALSO MAC
230 USER PARMBLK
CREATE FNAME 0 C, 63 ALLOT ( Our file has a name. This is where it is kept)
CREATE FPLACE 0 , ( This is the folder of our file. HFS! )
( Here we some "dirty" programming. I use the file manager directly.
This works, but the code is not very clear. Once the PARaMeterBLocK
is set, it doesn't need to be changed much. Read Inside Macintosh
for details on parameter blocks and the file system. )
: TEDDYLOAD ( Replace selection range with a file )
TE->SCRAP
PAD TEDDYGETFILE ( Use PAD as SFREPLY )
PAD C@ IF PAD 10 + FNAME 64 CMOVE
PAD 6 + W@ FPLACE !
PARMBLK 12 + OFF
PAD 10 + PARMBLK 18 + !
PAD 6 + W@ PARMBLK 22 + W!
0 PARMBLK 26 + W!
PARMBLK 28 + OFF
PARMBLK CALL OPEN
IF 10 CALL SYSBEEP ( Ouch! File Error )
ELSE
PARMBLK CALL GETEOF DROP
PARMBLK 28 + @
TEDDY.T @ @ 60 + W@
TEDDY.T @ @ 34 + W@ TEDDY.T @ @ 32 + W@ - -
+ 32767 < ( Does the result fit? )
IF TESCRAP.HANDLE @ DUP DUP
PARMBLK 28 + @ CALL SETHANDLESIZE DROP
CALL GETHANDLESIZE TESCRAP.LEN W!
CALL HLOCK DROP
TESCRAP.HANDLE @ @ PARMBLK 32 + !
TESCRAP.LEN W@ PARMBLK 36 + !
0 PARMBLK 44 + W!
0 PARMBLK 46 + !
PARMBLK CALL READ DROP
TESCRAP.HANDLE @ CALL HUNLOCK DROP
PARMBLK CALL CLOSE DROP
TEDDY.T @ CALL TEPASTE
CORRECT.CONTROL.RANGE
CORRECTSCROLL
ELSE 5 CALL SYSBEEP 5 CALL SYSBEEP ( Ouch! Text too long )
THEN
THEN
THEN
;
: TEDDYSAVE ( Save selection range )
TE->SCRAP
PAD FNAME TEDDYPUTFILE
PAD C@ IF PAD 10 + FNAME 64 CMOVE
PAD 6 + W@ FPLACE !
PARMBLK 12 + OFF
PAD 10 + PARMBLK 18 + !
PAD 6 + W@ PARMBLK 22 + W!
0 PARMBLK 26 + W!
PARMBLK 28 + OFF
PARMBLK CALL CREATE DROP
PARMBLK CALL OPEN DROP
TEDDY.T @ @ 34 + W@ TEDDY.T @ @ 32 + W@ -
?DUP 0= IF TEDDY.T @ @ 60 + W@ THEN
PARMBLK 28 + !
PARMBLK CALL SETEOF DROP
TEDDY.T @ @ 34 + W@ TEDDY.T @ @ 32 + W@ -
?DUP 0= IF
TEDDY.T @ @ 60 + W@ PARMBLK 36 + !
TEDDY.T @ @ 62 + @ @ PARMBLK 32 + !
ELSE
PARMBLK 36 + !
TEDDY.T @ @ 62 + @ @ TEDDY.T @ @ 32 + W@ +
PARMBLK 32 + !
THEN
0 PARMBLK 44 + W! PARMBLK 46 + OFF
PARMBLK CALL WRITE
PARMBLK CALL FLUSHFILE DROP
PARMBLK CALL CLOSE DROP
IF 10 CALL SYSBEEP
PARMBLK CALL DELETE
ELSE
PARMBLK CALL GETFILEINFO DROP
"TEXT PARMBLK 32 + ! ( Text files are of type TEXT! )
"MACA PARMBLK 36 + ! ( We create MacWrite files )
PARMBLK CALL SETFILEINFO DROP
THEN
PARMBLK 18 + OFF
PARMBLK CALL FLUSHVOL DROP
THEN
;
: TEDDYSAVEALL ( Save the whole file )
TEDDY.T @ @ 60 + W@ IF
TE->SCRAP
FNAME C@ IF
PARMBLK 12 + OFF
FNAME PARMBLK 18 + !
FPLACE @ PARMBLK 22 + W!
0 PARMBLK 26 + W!
PARMBLK 28 + OFF
PARMBLK CALL CREATE DROP
PARMBLK CALL OPEN DROP
TEDDY.T @ @ 60 + W@ PARMBLK 28 + !
PARMBLK CALL SETEOF DROP
TEDDY.T @ @ 60 + W@ PARMBLK 36 + !
TEDDY.T @ @ 62 + @ @ PARMBLK 32 + !
0 PARMBLK 44 + W! PARMBLK 46 + OFF
PARMBLK CALL WRITE
PARMBLK CALL FLUSHFILE DROP
PARMBLK CALL CLOSE DROP
IF 10 CALL SYSBEEP
PARMBLK CALL DELETE
ELSE
PARMBLK CALL GETFILEINFO DROP
"TEXT PARMBLK 32 + !
"MACA PARMBLK 36 + !
PARMBLK CALL SETFILEINFO DROP
THEN
PARMBLK 18 + OFF
PARMBLK CALL FLUSHVOL DROP
THEN THEN
;
: TFILEHANDLER ( Handle the file menu )
CASE 1 OF 0 TEDDY.T @ @ 60 + W@
TEDDY.T @ CALL TESETSELECT
TEDDYLOAD ENDOF
2 OF TEDDYSAVEALL ENDOF
3 OF TEDDY.T @ @ 32 + @
0 TEDDY.T @ @ 32 + !
TEDDYSAVE
TEDDY.T @ @ 32 + ! ENDOF
ENDCASE
;
: TEDDYMENUS ( Menu events are delivered here )
0 CALL HILITEMENU
CASE
APPLEID OF DAHANDLER ENDOF
TFILEID OF TFILEHANDLER ENDOF
TEDITID OF TEDITHANDLER ENDOF
ENDCASE
;
( This program has a menu on its window. There are 5 items on this menu
and the names of these items have to be somewhere. This was a simple
way to create an array of strings. )
: TITLES
CASE 0 OF " Select All" ENDOF
1 OF " Select Forward" ENDOF
2 OF " Select Backward" ENDOF
3 OF " Copy From Disk" ENDOF
4 OF " Save Selection" ENDOF ENDCASE
;
: DRAWTITLES ( Draw palette items )
PAD CALL GETPORT ( Get our window )
PAD @ TXFONT + W@ ( Save text charasteristics )
PAD @ TXSIZE + W@
PAD @ TXMODE + W@
1 CALL TEXTFONT ( Geneva )
9 CALL TEXTSIZE ( 9 point )
1 CALL TEXTMODE
5 0 DO ( 5 items in our palette )
2 I 90 * 2+ 15 OVER 91 + TEMR !RECT TEMR CALL ERASERECT
TEMR CALL FRAMERECT
I 90 * 47 +
I TITLES CALL STRINGWIDTH 2/ - ( Center the string )
12 CALL MOVETO I TITLES CALL DRAWSTRING
LOOP
CALL TEXTMODE ( Reset text charasteristics )
CALL TEXTSIZE
CALL TEXTFONT
;
168 USER UPDATE-HOOK ( Mach I has a lot of stupid hooks )
152 USER CONTENT-HOOK ( I have to live with them )
172 USER ACTIVATE-HOOK ( even if I do not like them )
CREATE SPORT 4 ALLOT ( Saved Port )
: GROWB ( Set the view rectangle )
TEDDY.W 20 + W@ 16 - 16 SCALE
TEDDY.W 22 + W@ 16 - + TEDDY.T @ @ 12 + !
;
: TEDDYUP ( Update events are delivered here )
( Note that the zoom box also generates an update event! )
SPORT CALL GETPORT ( Save some external window )
TEDDY.W CALL SETPORT ( Use the text editor window for updates )
TEDDY.W CALL BEGINUPDATE ( Inside Mac says this must be done )
GROWB
TEDDY.W 16 + CALL ERASERECT ( Erase area to be updated )
DRAWTITLES ( Draw palette titles )
TEDDY.W 16 + TEDDY.T @ CALL TEUPDATE
TEDDY.W CALL DRAWCONTROLS ( We have a scroll bar to update )
TEDDY.W CALL DRAWGROWICON
TEDDY.W CALL ENDUPDATE
SPORT @ CALL SETPORT ( Restore the port before the update )
;
( Given the number of the palette item that the mouse was pressed in,
this procedure tracks the mouse to see what the user really wants. )
: DOPALETTE.SUB { SELECTED | SLOC }
3 SELECTED 90 * 3 + 14 OVER 89 + TEMR !RECT
0 -> SLOC
BEGIN
CALL STILLDOWN
WHILE
@MOUSE TEMR CALL PTINRECT 0= 0= SLOC XOR
IF TEMR CALL INVERTRECT SLOC NOT -> SLOC THEN
REPEAT
SLOC IF TEMR CALL INVERTRECT SELECTED 1+ ELSE 0 THEN
;
: DOPALETTE ( There is a mousedown in the palette )
@MOUSE L_EXT
2 - 90 / DOPALETTE.SUB
CASE 1 OF 0 TEDDY.T @ @ 60 + W@
TEDDY.T @ CALL TESETSELECT ENDOF
2 OF TEDDY.T @ @ 32 + W@ TEDDY.T @ @ 60 + W@
TEDDY.T @ CALL TESETSELECT ENDOF
3 OF 0 TEDDY.T @ @ 34 + W@
TEDDY.T @ CALL TESETSELECT ENDOF
4 OF TEDDYLOAD ENDOF
5 OF TEDDYSAVE ENDOF
ENDCASE
;
( Dotextclick looks at the shift key and calls TeClick.
0= 0= is the equivalent of MacForth's "Boolean". )
: DOTEXTCLICK ( MOUSEPT -- Click...no ammo in a mouse... )
EVENT-RECORD 14 + W@ 512 AND 0= 0= TEDDY.T @ CALL TECLICK
TEDDY.W CALL DRAWCONTROLS
;
2 2 15 452 RECT BUTTONRECT ( This is the rect of our palette )
: CONTENTCLICK { | MOUSEPT }
RUN-CONTENT
TEDDY.W CALL SETPORT
EVENT-RECORD 10 + @ PAD ! PAD CALL GLOBALTOLOCAL
PAD @ -> MOUSEPT MOUSEPT BUTTONRECT CALL PTINRECT
IF DOPALETTE
ELSE MOUSEPT TEDDY.T @ @ 8 + CALL PTINRECT
IF MOUSEPT DOTEXTCLICK
THEN
THEN
;
( We set the dest and view rectangles )
: INITTEXT
18 4 TEDDY.W 20 + W@ 16 - TEDDY.W 22 + W@ 16 - TEMR !RECT
TEMR PAD 8 CMOVE
1 PAD 2+ W! TEMR PAD CALL TENEW TEDDY.T !
-1 TEDDY.T @ @ 72 + W!
;
( The following code handles the scroll bar )
( The thumb is called separately...Mach I manual for details )
: DOTHUMB
TEDDY.T @ @ W@ L_EXT 18 - NEGATE
TEDDY.SB @ CALL GETCTLVALUE 11 * -
0 SWAP TEDDY.T @ CALL TESCROLL
;
: DOARROW
TEDDY.SB @ CALL GETCTLVALUE SWAP OVER +
TEDDY.SB @ SWAP CALL SETCTLVALUE
TEDDY.SB @ CALL GETCTLVALUE -
11 * 0 SWAP TEDDY.T @ CALL TESCROLL
;
: TEDDYBAR
CASE
UPARROW OF -1 DOARROW ENDOF
DOWNARROW OF 1 DOARROW ENDOF
PAGEUP OF TEDDY.W 20 + W@ 40 - -11 / -1 MIN DOARROW ENDOF
PAGEDOWN OF TEDDY.W 20 + W@ 40 - 11 / 1 MAX DOARROW ENDOF
ENDCASE
;
: TEDDYCONTROL ( Control )
CASE ( In case of multiple controls... )
TEDDY.SB @ OF TEDDYBAR ENDOF
ENDCASE
;
: TEDDYCONTROL2 ( Control/Part )
CASE ( In case of multiple controls and parts... )
TEDDY.SB @ OF CASE THUMB OF DOTHUMB ENDOF ENDCASE ENDOF
ENDCASE
;
( We go to sleep when we are not in use. Deactivate events look like
Activate events if the program doesn't look hard enough )
: ACTIVATE-HANDLER
RUN-ACTIVATE
EVENT-RECORD 14 + W@ 1 AND
IF WAKE STATUS TASK-> TEDDY.TASK W!
ACTIVE? ON
TEDDY.T @ CALL TEACTIVATE
SCRAP->TE
ELSE SLEEP STATUS TASK-> TEDDY.TASK W!
TEDDY.T @ CALL TEDEACTIVATE
ACTIVE? OFF
TE->SCRAP
CLEAR.TESCRAP
THEN
;
( The Enter key does indentation, return doesn't )
: TEDDY.ENTER { | LOCATION CNTER NSPACES }
TEDDY.T @ @ 62 + @ @ -> LOCATION
TEDDY.T @ @ 32 + W@ 1- -> CNTER
0 -> NSPACES
BEGIN
LOCATION CNTER + C@ 13 = NOT
CNTER 1+ 0> AND
WHILE
LOCATION CNTER + C@ 32 = IF NSPACES 1+ -> NSPACES
ELSE 0 -> NSPACES THEN
CNTER 1- -> CNTER
REPEAT
13 TEDDY.T @ CALL TEKEY
NSPACES 0> IF
NSPACES 0 DO
32 TEDDY.T @ CALL TEKEY
LOOP THEN
;
( These are done only once, so we have a flag to show if the routine
must be called. Always Workspace before testing TEDDY or you will
save the flag in the wrong state! )
CREATE CONFIGFLAG 0 ,
: CONFIGURE.TEDDY
TEDDY.W ADD
TEDDY.W TEDDY.TASK BUILD
TEDDY.BAR ADD
TEDDY.BAR APPLEMENU ADD
TEDDY.BAR TFILE ADD
TEDDY.BAR TEDITMENU ADD
TEDDY.W TEDDY.SB ADD
INITTEXT
ADD.DRVRS
TEDDY.BAR TEDDY.TASK MBAR>TASK
TEDDY.TASK
CONFIGFLAG ON
;
( The following can be done the first time )
: TEDDYGO
CONFIGFLAG @ NOT IF CONFIGURE.TEDDY ACTIVATE THEN
ACTIVE? OFF
['] TEDDYMENUS MENU-VECTOR !
['] TEDDYUP UPDATE-HOOK !
['] CONTENTCLICK CONTENT-HOOK !
['] ACTIVATE-HANDLER ACTIVATE-HOOK !
['] TEDDYCONTROL TEDDY.SB 4 + !
['] TEDDYCONTROL2 CONTROL-VECTOR !
['] CLICKPROC TEDDY.T @ @ 42 + !
100 CURMAX ! CORRECT.CONTROL.RANGE
TEDDY.SB @ ['] TEDDY.S2 !
TEDDY.W ['] TEDDY.W2 !
TEDDY.T @ ['] TEDDY.T2 !
BEGIN ( This is the beginning of our "Event" loop )
ACTIVE? @ IF TEDDY.T @ CALL TEIDLE ( Caret blink, blink, blink...)
?TERMINAL ?DUP IF
1 24 SCALE AND IF ( Is it a cmd key? )
KEY CALL MENUKEY DROP
ELSE
KEY CASE
3 OF TEDDY.ENTER ENDOF
9 OF 4 0 DO 32 TEDDY.T @ CALL TEKEY LOOP ENDOF
TEDDY.T @ CALL TEKEY 0 ( EndCase drops! )
ENDCASE
CORRECTSCROLL ( Autoscrolling )
CORRECT.CONTROL.RANGE
CORRECT.CONTROL
THEN
THEN
THEN
PAUSE ( This is the equivalent of GetNextEvent )
AGAIN
;
: TED ( TED always starts the editor...even if you hide the window )
CONFIGFLAG @ NOT IF TEDDYGO THEN
TEDDY.W CALL SHOWWINDOW
TEDDY.W CALL SELECTWINDOW
TEDDY.BAR @ CALL SETMENUBAR
CALL DRAWMENUBAR
QUIT
;